<?php

/**
 * @package mikrokosmos
 * mk swf actions model file created on oct-2004
 * jaco_at_pixeldump_dot_org
 */


// actionslist
$swfActions = array();
$swfActions["endFlag"]	= 0x00;
$swfActions["end"]		= "";		// for flasm compatibility
$swfActions["label"]		= "";	// for flasm compatibility

//---------------------------
// swf3 action model
//---------------------------

$swfActions["gotoFrame"]		= 0x81;
$swfActions["getURL"]			= 0x83;
$swfActions["nextFrame"]		= 0x04;
$swfActions["previousFrame"]	= 0x05;
$swfActions["play"]				= 0x06;
$swfActions["stop"]				= 0x07;
$swfActions["toggleQuality"]	= 0x08;
$swfActions["stopSounds"]		= 0x09;
$swfActions["waitForFrame"] 	= 0x8a;
$swfActions["setTarget "]		= 0x8b;
$swfActions["goToLabel "]		= 0x8c;


//---------------------------
// swf4 action model
//---------------------------

$swfActions["push"]				= 0x96;
$swfActions["pop"]				= 0x17;
$swfActions["add"]				= 0x0A;
$swfActions["subtract"]			= 0x0B;
$swfActions["multiply"]			= 0x0C;
$swfActions["divide"]			= 0x0D;
$swfActions["equals"]			= 0x0E;
//$swfActions["less"]				= 0x0F;
$swfActions["lessThanOld"]		= 0x0F; // for flasm compatibility
$swfActions["and"]				= 0x10;
$swfActions["or"]				= 0x11;
$swfActions["not"]				= 0x12;
$swfActions["stringEquals"]		= 0x13;
$swfActions["stringLength"]		= 0x14;
$swfActions["stringAdd"]		= 0x21;
$swfActions["stringExtract"]	= 0x15;
$swfActions["stringLess"]		= 0x29;
$swfActions["mbStringLength"]	= 0x31;
$swfActions["mbStringExtract"]	= 0x35;
$swfActions["toInteger"]		= 0x18;
$swfActions["charToAscii"]		= 0x32;
$swfActions["asciiToChar"]		= 0x33;
$swfActions["mbCharToAscii"]	= 0x36;
$swfActions["mbAsciiToChar"]	= 0x37;
//$swfActions["jump"]				= 0x99;
$swfActions["branch"]			= 0x99;	// for flasm compatibility
//$swfActions["if"]				= 0x9D;
$swfActions["branchIfTrue"]		= 0x9D; // for flasm compatibility
$swfActions["call"]				= 0x9E;
$swfActions["getVariable"]		= 0x1C;
$swfActions["setVariable"]		= 0x1D;
$swfActions["getURL2 "]			= 0x9A;
$swfActions["gotoFrame2 "]		= 0x9F;
$swfActions["setTarget2"]		= 0x20;
$swfActions["getProperty"]		= 0x22;
$swfActions["setProperty"]		= 0x23;
$swfActions["removeSprite"]		= 0x25;
$swfActions["startDrag"]		= 0x27;
//$swfActions["endDrag"]			= 0x28;
$swfActions["stopDrag"]			= 0x28;	// for flasm compatibility
$swfActions["waitForFrame2"]	= 0x8D;
$swfActions["trace"]			= 0x26;
$swfActions["gGetTime"]			= 0x34;
$swfActions["randomNumber"]		= 0x30;

//---------------------------
// swf5 action model
//---------------------------

$swfActions["targetPath"]		= 0x45;
$swfActions["callMethod"]		= 0x52;
//$swfActions["constantPool"]		= 0x88;
$swfActions["constants"]		= 0x88;	// for flasm compatibility
//$swfActions["defineFunction"]	= 0x9B;
$swfActions["function"]			= 0x9B;	// for flasm compatibility
//$swfActions["defineLocal"]		= 0x3C;
$swfActions["varEquals"]		= 0x3C;	// for flasm compatibility
$swfActions["defineLocal2"]		= 0x41;
$swfActions["delete"]			= 0x3A;
$swfActions["delete2"]			= 0x3B;
$swfActions["enumerate"]		= 0x46;
$swfActions["equals2"]			= 0x49;
$swfActions["getMember"]		= 0x4E;
$swfActions["initArray"]		= 0x42;
$swfActions["initObject"]		= 0x43;
$swfActions["newMethod"]		= 0x53;
//$swfActions["newObject"]		= 0x40;
$swfActions["new"]				= 0x40; // for flasm compatibility
$swfActions["setMember"]		= 0x4F;
$swfActions["with"]				= 0x94;
$swfActions["toNumber"]			= 0x4A;
$swfActions["toString"]			= 0x4B;
$swfActions["typeOf"]			= 0x44;
$swfActions["add2"]				= 0x47;
//$swfActions["add"]				= 0x47;
//$swfActions["less2"]			= 0x48; // for flasm compatibility
$swfActions["lessThan"]			= 0x48;
$swfActions["modulo"]			= 0x3F;
$swfActions["bitAnd"]			= 0x60;
$swfActions["bitLShift"]		= 0x63;
$swfActions["bitOr"]			= 0x61;
$swfActions["bitRShift"]		= 0x64;
$swfActions["bitURShift"]		= 0x65;
$swfActions["bitXor"]			= 0x62;
$swfActions["decrement"]		= 0x51;
$swfActions["increment"]		= 0x50;
//$swfActions["pushDuplicate"]	= 0x4C;
$swfActions["dup"]				= 0x4C; // for flasm compatibility
$swfActions["return"]			= 0x3E;
//$swfActions["storeRegister"]	= 0x87;
$swfActions["setRegister"]		= 0x87;	// for flasm compatibility
$swfActions["callFunction"]		= 0x3D;
//$swfActions["stackSwap"]		= 0x4D;
$swfActions["exch"]				= 0x4D; // for flasm compatibility, TODO: verify

//---------------------------
// swf6 action model
//---------------------------

//$swfActions["doInitActionTag(){} // it is a tag to be implemented
$swfActions["instanceOf"]		= 0x54;
$swfActions["enumerate2"]		= 0x55;
$swfActions["strictEquals"]		= 0x66;
//$swfActions["greater"]		= 0x67;
$swfActions["greaterThan"]		= 0x67; // for flasm compatibility
$swfActions["stringGreater"]	= 0x68;


//---------------------------
// swf7 action model
//---------------------------

//$swfActions["defineFunction2"]	= 0x8E;
$swfActions["function2"]		= 0x8E; // for flasm compatibilty
$swfActions["extends"]			= 0x69;
$swfActions["castOp"]			= 0x2B;
$swfActions["implementsOp"]		= 0x2C;
$swfActions["try"]				= 0x8F;
$swfActions["throw"]			= 0x2A;

// ---------------------- end of action models -----------------


// "type" library
$asTL = array();
$asTL[0] = "AS_STRING";			// 0 = string literal
$asTL[1] = "AS_FP";				// 1 = floating-point literal
$asTL[2] = "AS_NULL";			// 2 = null
$asTL[3] = "AS_UNDEFINED";		// 3 = undefined
$asTL[4] = "AS_REGISTER";		// 4 = register
$asTL[5] = "AS_BOOL";			// 5 = boolean
$asTL[6] = "AS_DOUBLE";			// 6 = double
$asTL[7] = "AS_INT";			// 7 = integer
$asTL[8] = "AS_CONST8";			// 8 = constant 8
$asTL[9] = "AS_CONST16";		// 9 = constant 16

$asTL[10] = "AS_BYTE";			// byte
$asTL[11] = "AS_WORD";			// word

$keyCodes = array();
$keyCodes["x1"]  = "_LEFT";
$keyCodes["x2"]  = "_RIGHT";
$keyCodes["x3"]  = "_HOME";
$keyCodes["x4"]  = "_END";
$keyCodes["x5"]  = "_INSERT";
$keyCodes["x6"]  = "_DELETE";
$keyCodes["x8"]  = "_BACKSPACE";
$keyCodes["x13"] = "_ENTER";
$keyCodes["x14"] = "_UP";
$keyCodes["x15"] = "_DOWN";
$keyCodes["x16"] = "_PAGEUP";
$keyCodes["x17"] = "_PAGEDOWN";
$keyCodes["x18"] = "_TAB";
$keyCodes["x19"] = "_ESCAPE";


// look-up tables
$swfActionTrans_luStr = ""; // look-up string for verify action record presence
$swfActionTrans_luAr = array(); // look-up array to retrieve action name knowing its actionCode
$swfActionNames = array();	// simple action names list

foreach ($swfActions as $a => $ac){

	//echo "<br />actionName: " . $a .", bytecode: " .$ac;

	$acStr = "x" .$ac;
	$swfActionTrans_luAr[$acStr] = $a;
	$swfActionTrans_luStr .= $acStr ."-" .$a .",";
	$swfActionNames[] = $a;
}


// clip action flags
$caFlags = array();
$caFlags["keyUp"]		= 0x80;				// 0x01 key release
$caFlags["keyDown"]		= 0x40;				// 0x02 key press
$caFlags["mouseUp"]		= 0x20;				// 0x04 mouse release
$caFlags["mouseDown"]   = 0x10;				// 0x08 mouse down
$caFlags["mouseMove"]   = 0x08;				// 0x10 mouse move
$caFlags["unload"]		= 0x04;				// 0x20 clip unload
$caFlags["enterFrame"]  = 0x02;				// 0x40 enterFrame
$caFlags["load"]		= 0x01;				// 0x40 load


$caFlags["dragOver"] 	= 0x8000;			//
$caFlags["rollOut"]		= 0x4000;			//
$caFlags["rollOver"] 	= 0x2000;			//
$caFlags["releaseOutside"] 	= 0x1000;		//
$caFlags["release"] 	= 0x0800;			//
$caFlags["press"] 		= 0x0400;			//
$caFlags["initialize"] 	= 0x0200;			//
$caFlags["data"] 		= 0x0100;			//

// from player 6
$caFlags["event"] 		= 0x040000;			//
$caFlags["keyPress"] 	= 0x020000;			//
$caFlags["dragOut"]		= 0x010000;			//

$cafNames = array();
foreach($caFlags as $k => $v) $cafNames["x" .$v] = $k;

/**
 * check if a given action name is supported
 * by actionscript compiler
 */
function is_supported_action($actionName){
	global $swfActionNames;
	return in_array($actionName, $swfActionNames, true);
}

/**
 * returns a string representing keyPress code
 * in flasm compliant behavior
 */
function get_keyPress_code($v){
	global $keyCodes;
	if($v < 20) return $keyCodes["x" .$v];
	return chr($v);
}

//---------------------------
// action WRITE compiler kit
//---------------------------

function write_start_doAction(){
	return SWFTag_long_header(0x0c, 0);
}

function write_end_doAction($daStr){

	$daStr .= NIL;
	$daLength = swf_write_dword(strlen($daStr) - 6); // body length;

	$daStr[2] = $daLength[3];
	$daStr[3] = $daLength[2];
	$daStr[4] = $daLength[1];
	$daStr[5] = $daLength[0];

	return $daStr;
}

// swf3
function write_GotoFrame($nmb){

	$str = chr(0x81);
	$str .= chr(0x02);
	$str .= swf_write_word($nmb);

	return $str;
}

function write_GetURL($url, $targetStr){

	$str = chr(0x83);
	$str .= swf_write_word(strlen($url) + strlen($targetStr));
	$str .= swf_write_string($url);
	$str .= swf_write_string($targetStr);

	return $str;
}

function write_WaitForFrame($nmb, $skipActions){

	$str = chr(0x8a);
	$str .= chr(0x03);
	$str .= swf_write_word($nmb);
	$str .= chr($skipActions);

	return $str;
}

function write_SetTarget($targetClip){

	$str = chr(0x8b);
	$str .= swf_write_word(strlen($targetClip) + 1);
	$str .= swf_write_string($targetClip);

	return $str;
}

function write_GotToLabel($frameLabel){

	$str = chr(0x8c);
	$str .= swf_write_word(strlen($frameLabel) + 1);
	$str .= swf_write_string($frameLabel);

	return $str;
}

// swf4


function write_ConstantPool($ard = array()){

	$buf = chr(0x88);
	$paramBuf = "";

	foreach($ard["params"] as $p){
		$paramBuf .= swf_string($p["value"]);
	}

	$buf .= swf_word(strlen($paramBuf) + 2);
	$buf .= swf_word(count($ard["params"]));

	$buf .= $paramBuf;

	return $buf;
}

/**
 * alias of write_ConstantPool
 */
function write_Constants($ard = array()){
	return write_ConstantPool($ard);
}

/**
 * compile definefunction header
 * codeblock has to be compiled apart
 */
function write_DefineFunction($ard = array()){

	if(!isset($ard["params"])) $ard["params"] = array();
	if(!isset($ard["functionName"])) $ard["functionName"] = "";


	$params = $ard["params"];
	$pCount = count($params);
	$buf = chr(0x9b);


	$paramBuf = swf_string($ard["functionName"]); // function name
	$paramBuf .= swf_word($pCount);

	for($i = 0; $i < $pCount; $i++){
		$p = $params[$i];
		$paramBuf .= swf_string($p["value"]);
	}

	$paramBuf .= swf_word($ard["codeSize"]);

	$buf .= swf_word(strlen($paramBuf));
	$buf .= $paramBuf;

	return $buf;
}

/**
 * alias of write_DefineFunction
 */
function write_Function($ard = array()){
	return write_DefineFunction($ard);
}


// swf7
function write_DefineFunction2($ard = array()){

	if(!isset($ard["params"])) $ard["params"] = array();
	if(!isset($ard["functionName"])) $ard["functionName"] = "";

	$params = $ard["params"];
	$pCount = count($params);
	$buf = chr(0x8e);

	$paramBuf = swf_string($ard["functionName"]); // function name
	$paramBuf .= swf_word($pCount);

	$paramBuf .= chr($ard["registerCount"]);

	$plFlags = "";

	$fld = $ard["functionFlags"];

	$plFlags .= $fld["plParent"]		  ? "1" : "0";
	$plFlags .= $fld["plRoot"]			  ? "1" : "0";
	$plFlags .= $fld["suppressSuper"]	  ? "1" : "0";
	$plFlags .= $fld["plSuper"]			  ? "1" : "0";
	$plFlags .= $fld["suppressArguments"] ? "1" : "0";
	$plFlags .= $fld["plArguments"]		  ? "1" : "0";
	$plFlags .= $fld["suppressThis"]	  ? "1" : "0";
	$plFlags .= $fld["plThis"]			  ? "1" : "0";

	$plFlags .= "0000000"; // reserved
	$plFlags .= $fld["plGlobal"]		  ? "1" : "0";

	$buf .= swf_bin($plFlags);


	for($i = 0; $i < $pCount; $i++){
		$p = $params[$i];
		$paramBuf .= swf_string($p["value"]);
	}

	$paramBuf .= swf_word($ard["codeSize"]);

	$buf .= swf_word(strlen($paramBuf));
	$buf .= $paramBuf;

	return $buf;

}

/**
 * alias of write_DefineFunction2
 */
function write_Function2($ard = array()){
	return write_DefineFunction2($ard);
}



// actionpush is a key composite action
// $arItems is an Array containing associative arrays
// each associative array contains three field:
// itemName, itemValue, itemType

function write_Push($ard = array()){

	$buf = chr(0x96);

	$paramBuf = "";

	foreach($ard["params"] as $p){

		$code = $p["code"];
		$value = $p["value"];
		$paramBuf .= chr($code);

		//note that AS_NULL, AS_UNDEFINED has no body

		if($code ==  AS_STRING){
			$paramBuf .= swf_string($value);
		}
		else if($code == AS_FP){
			$paramBuf .= swf_dword($value);
		}
		else if($code == AS_REGISTER){
			$paramBuf .= chr($value);
		}
		else if($code == AS_BOOL){
			$paramBuf .= chr($value);
		}
		else if($code == AS_DOUBLE){
			$paramBuf .= swf_double($value);
		}
		else if($code == AS_INT){
			$paramBuf .= swf_dword($value);
		}
		else if($code == AS_CONST8){
			$paramBuf .= chr($value);
		}
		else if($code == AS_CONST16){
			$paramBuf .= swf_word($value);
		}
	}

	$buf .= swf_word(strlen($paramBuf));
	$buf .= $paramBuf;

	return $buf;
}

function store_literal($str){
	return chr(0x00) .swf_write_string($str);
}

function store_integer($varName, $intVal){
	$str = store_literal($varName);
	$str .= chr(0x07);
	$str .= swf_write_dword($intVal);

	return $str;
}

// end

function write_Jump($ard){

	$buf = chr(0x99);
	$buf .= swf_word(2);
	$buf .= swf_word($ard["params"][0]["value"]);
	return $buf;
}

/**
 * alias of write_Jump
 */
function write_Branch($ard){
	return write_Jump($ard);
}

function write_If($ard){

	$buf = chr(0x9D);
	$buf .= swf_word(2);
	$buf .= swf_word($ard["params"][0]["value"]);
	return $buf;
}

/**
 * alias of write_If
 */
function write_BranchIfTrue($ard){
	return write_If($ard);
}

function write_Call(){ return chr(0x9E); }

function write_GetURL2($method = "none"){

	$mtAr = Array();
	$mtAr["none"] = 0;
	$mtAr["GET"] = 1;
	$mtAr["POST"] = 2;

	$str = chr(0x9A);
	$str .= chr($mtAr[$method]);

	return $str;
}

function write_GotoFrame2($playFlag){

	$str = chr(0x9F);
	$str .= chr($playFlag);
	return $str;
}

/*
insert property list for mnemonic use
*/
function write_WaitForFrame2($skipCount){

	$str = chr(0x8D);
	$str .= chr($skipCount);
	return $str;
}

// swf5

function write_With2(){ return chr(0x94); }

function write_With(){ return chr(0x94); }

function write_StoreRegister($ard){

	$buf = chr(0x87);
	$buf .= swf_word(1);
	$buf .= chr($ard["params"][0]["value"]);
	return $buf;
}

/**
 * alias of write_StoreRegister
 */
function write_SetRegister($ard){
	return write_StoreRegister($ard);
}


// --------------------------
// actions script READ kit
// --------------------------
//
// note: every function expects raw binary Data
// WITHOUT action tag header (1 byte)
//



/*
 * these action records return actionCode only
 * please refer to get_actionCode and get_actionName

--- swf3
NextFrame
PreviousFrame
Play
Stop
ToggleQuality
StopSounds

--- swf4
Pop
Add
Subtract
Multiply
Divide
Equals
Less
And
Or

StringEquals
StringLength
StringAdd
StringExtract
StringLess
MBStringLength
MBStringExtract
ToInteger
CharToAscii
AsciiToChar
MBCharToAscii
MBAsciiToChar

Call
GetVariable
SetVariable

SetTarget2
GetProperty
SetProperty
RemoveSprite
StartDrag
EndDrag

Trace
GetTime
RandomNumber

---- swf5
CallFunction
CallMethod

DefineLocal (in flasm: varEquals)
DefineLocal2
Enumerate
Equals
Equals2
GetMember
InitArray
InitObject
NewMethod
NewObject
SetMember

ToNumber
ToString
TypeOf
Add2
Less2
Modulo
BitAnd
BitLShift
BitOr
BitRShift
BitURShift
BitXor
Decrement
Increment
PushDuplicate
Return
StackSwap

-- swf6
InstanceOf
Enumerate2
StrictEquals
Greater
StringGreater

-- swf7
Extends
CastOp
Implements
read_Throw
*/


/*
 * please note: all read... return ONLY parameters
 * because function name already containg the meanings of actionCode
 */

// swf3
function read_GotoFrame($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params = array();
	$params[0]["code"] = AS_WORD;
	$params[0]["type"] = get_paramType(AS_WORD);
	$params[0]["value"] = ui16dec(substr($buf, 3, 2));

	$ard["params"] = $params;
	return $ard;
}

function read_GetURL($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params = array();

	$params[0]["code"] = AS_STRING;
	$params[0]["type"] = get_paramType(AS_STRING);
	$params[0]["value"] = read_swf_string(substr($buf, 3));

	$params[1]["code"] = AS_STRING;
	$params[1]["type"] = get_paramType(AS_STRING);
	$params[1]["value"] = read_swf_string(substr($buf, strlen($params[0]["value"]) + 4));

	$ard["params"] = $params;
	return $ard;
}



function read_WaitForFrame($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_WORD;
	$params[0]["type"] = get_paramType(AS_WORD);
	$params[0] = bin2dec(substr($buf, 3 ,2));

	$params[1]["code"] = AS_BYTE;
	$params[1]["type"] = get_paramType(AS_BYTE);
	$params[1] = bin2dec($buf[5]);

	$ard["params"] = $params;
	return $ard;
}

function read_SetTarget($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_STRING;
	$params[0]["type"] = get_paramType(AS_STRING);
	$params[0]["meaning"] = "targetName";
	$params[0]["value"] = swf_string(substr($buf, 3));

	$ard["params"] = $params;
	return $ard;
}

function read_GoToLabel($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_STRING;
	$params[0]["type"] = get_paramType(AS_STRING);
	$params[0]["value"] = read_swf_string(substr($buf, 3));

	$ard["params"] = $params;
	return $ard;
}

function read_Push($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$length = $ard["totalLength"] - 3;
	//$length = ui16dec(substr($buf, 1, 2));
	$pBody = substr($buf, 3);
	$pLength = strlen($pBody);

	$ofst = 0;

	do {
		$pidx = count($params);
		$t = ui8dec($pBody[$ofst]);
		$ofst++;

		$params[$pidx]["code"] = $t;
		$params[$pidx]["type"] = get_paramType($t);

		if($t == AS_STRING){

			$params[$pidx]["value"] = read_swf_string(substr($pBody, $ofst), true);
			$ofst += strlen($params[$pidx]["value"]) + 1;
		}
		else if($t == AS_FP){
			$fpStr = get_binData_string(substr($pBody, $ofst, 4));
			$params[$pidx]["value"] = fp_binStr_float($fpStr);
			$ofst += 4;
		}
		else if($t == AS_NULL){
			$params[$pidx]["value"] = "NULL";
		}
		else if($t == AS_UNDEFINED){
			$params[$pidx]["value"] = "undefined";
		}
		else if($t == AS_REGISTER){
			$params[$pidx]["value"] = ui8dec($pBody[$ofst]);
			$ofst++;
		}
		else if($t == AS_BOOL){
			$params[$pidx]["value"] = ui8dec($pBody[$ofst]);
			$ofst++;
		}
		else if($t == AS_DOUBLE){
			$params[$pidx]["value"] = si64double(substr($pBody, $ofst, 8));
			$ofst += 8;
		}
		else if($t == AS_INT){
			$params[$pidx]["value"] = si32dec(substr($pBody, $ofst, 4));
			$ofst += 4;
		}
		else if($t == AS_CONST8){
			$params[$pidx]["value"] = ui8dec($pBody[$ofst]);
			$ofst++;
		}
		else if($t == AS_CONST16){
			$params[$pidx]["value"] = ui16dec(substr($pBody, $ofst, 2));
			$ofst += 2;
		}
	} while($ofst < $length);

	$ard["params"] = $params;
	return $ard;
}


function read_Not($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_BOOL;
	$params[0]["type"] = get_paramType(AS_BOOL);
	$params[0]["value"] = si8dec($buf[3]);

	$ard["params"] = $params;
	return $ard;
}


function read_Jump($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_WORD;
	$params[0]["type"] = get_paramType(AS_WORD);
	$params[0]["value"] = si16dec(substr($buf, 3, 2));

	$ard["params"] = $params;
	return $ard;
}

/**
 * alias of read_Jump
 */
function read_Branch($buf){
	return read_Jump($buf);
}

function read_If($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_WORD;
	$params[0]["type"] = get_paramType(AS_WORD);
	$params[0]["value"] = si16dec(substr($buf, 3, 2));

	$ard["params"] = $params;
	return $ard;
}

/**
 * alias of read_If
 */
function read_BranchIfTrue($buf){
	return read_If($buf);
}

/**
 * this is a buggy action due to high bit set (0x9E)
 * but there are no parameters
 */
function read_call($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	//$ard["params"] = $params;
	return $ard;
}

function read_GetURL2($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$pStr = get_binData_string($buf[3]);
	$svm = "000000" .substr($pStr, 0, 2);

	$params[0]["code"] = "flagMethod";
	$params[0]["type"] = "flag";
	$params[0]["value"] = bindec($svm);

	$params[1]["code"] = "flagLoadTarget";
	$params[1]["type"] = "flag";
	$params[1]["value"] = (int) $pStr[6];

	$params[2]["code"] = "flagLoadVariables";
	$params[2]["type"] = "flag";
	$params[2]["value"] = (int) $pStr[7];

	$ard["params"] = $params;
	return $ard;
}

function read_GotoFrame2($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();
	$pStr = get_binData_string($buf[3]);

	$params[0]["code"] = "flagSceneBias";
	$params[0]["type"] = "flag";
	$params[0]["value"] = (int) $pStr[6];

	$params[1]["code"] = "flagPlay";
	$params[1]["type"] = "flag";
	$params[1]["value"] = (int) $pStr[7];

	if($params[0]["value"]){
		$params[2]["code"] = AS_WORD;
		$params[2]["type"] = get_paramType(AS_WORD);
		$params[2]["value"] = substr($buf, 4 ,2);
	}

	$ard["params"] = $params;
	return $ard;
}



function read_WaitForFrame2($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$params[0]["code"] = AS_BYTE;
	$params[0]["type"] = get_paramType(AS_BYTE);
	$params[0]["value"] = bin2dec($buf[3]);

	$ard["params"] = $params;
	return $ard;
}


function read_ConstantPool($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));

	$params = array();
	$pCount = ui16dec(substr($buf, 3, 2));

	$cpBody = substr($buf, 5);
	$ofst = 0;

	for($i = 0; $i < $pCount; $i++){
		$params[$i]["code"] = AS_STRING;
		$params[$i]["type"] = get_paramType(AS_STRING);
		$params[$i]["value"] = read_swf_string(substr($cpBody, $ofst), true);
		$ofst += strlen($params[$i]["value"]) + 1;
	}

	$ard["params"] = $params;
	return $ard;
}

/**
 * alias of read_ConstantPool
 */
function read_Constants($buf){
	return read_ConstantPool($buf);
}

function read_DefineFunction($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();

	$ofst = 3;
	$ard["functionName"] = read_swf_string(substr($buf, $ofst));
	$ofst += strlen($ard["functionName"]) + 1;

	$pCount = ui16dec(substr($buf, $ofst, 2));
	$ofst += 2;

	for($i = 0; $i < $pCount; $i++){
		$params[$i]["code"] = AS_STRING;
		$params[$i]["type"] = get_paramType(AS_STRING);
		$params[$i]["value"] = read_swf_string(substr($buf, $ofst));
		$ofst += strlen($params[$i]["value"]) + 1;
	}

	$ard["codeSize"] = ui16dec(substr($buf, $ofst, 2));
	$ard["params"] = $params;

	return $ard;
}

/**
 * alias of read_DefineFunction
 */
function read_Function($buf){
	return read_DefineFunction($buf);
}

function read_With($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$params = array();
	$ard["codeSize"] = ui16dec(substr($buf, 3, 2));
	$ard["withBlock"] = "";

	if($ard["totalLength"] > 5)
		$ard["withBlock"] = read_swf_string(substr($buf, 5));

	return $ard;
}


function read_StoreRegister($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));

	$params = array();

	$params[0]["code"] = AS_BYTE;
	$params[0]["type"] = get_paramType(AS_BYTE);
	$params[0]["value"] = ui16dec($buf[3]);

	$ard["params"] = $params;
	return $ard;
}

/**
 * alias of read_StoreRegister
 */
function read_SetRegister($buf){
	return read_StoreRegister($buf);
}

// swf7
function read_DefineFunction2($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$buf = substr($buf, 0, $ard["totalLength"]);
	$ard["actionCode"] = 0x8e;

	$ofst = 3;
	$ard["functionName"] = read_swf_string(substr($buf, $ofst));
	$ofst += strlen($ard["functionName"]) + 1;

	$pCount = ui16dec(substr($buf, $ofst, 2)); // num params
	$ofst += 2;

	$rCount = ui8dec($buf[$ofst]); // register count
	$ofst++;

	$fFlags = substr($buf, $ofst, 2);	// function flags
	$ard["functionFlags"] = read_DefineFunction2_flags($fFlags);
	$ofst += 2;

	$rParams = array();

	for($i = 0; $i < $pCount; $i++){
		$rParams[$i] = array();

		$rParams[$i]["index"] = ui8dec($buf[$ofst]);
		$ofst++;

		if($rParams[$i]["index"]){
			$rParams[$i]["code"] = AS_REGISTER;
			$rParams[$i]["type"] = get_paramType(AS_REGISTER);
		}
		else {
			$rParams[$i]["code"] = AS_STRING;
			$rParams[$i]["type"] = get_paramType(AS_STRING);
		}
		$rParams[$i]["value"] = read_swf_string(substr($buf, $ofst));
		$ofst += strlen($rParams[$i]["value"]) + 1;
	}

	$ard["params"] = $rParams;
	$ard["codeSize"] = ui16dec(substr($buf, $ard["totalLength"] - 2, 2));

	return $ard;
}


/**
 * read 2 byte, return function flags
 * specific for defineFunction 2
 */
function read_DefineFunction2_flags($fFlags){

	$functionFlags = array();

	$spFlag1 = get_binData_string($fFlags[0]);
	$spFlag2 = get_binData_string($fFlags[1]);

	$functionFlags["plParent"]		= (int) $spFlag1[0];
	$functionFlags["plRoot"]		= (int) $spFlag1[1];
	$functionFlags["suppressSuper"]		= (int) $spFlag1[2];
	$functionFlags["plSuper"]		= (int) $spFlag1[3];
	$functionFlags["suppressArguments"] = (int) $spFlag1[4];
	$functionFlags["plArguments"]  = (int) $spFlag1[5];
	$functionFlags["suppressThis"]		= (int) $spFlag1[6];
	$functionFlags["plThis"]		= (int) $spFlag1[7];

	$functionFlags["reserved"]		= 0;
	$functionFlags["plGlobal"]		= (int) $spFlag2[7];

	return $functionFlags;
}

/**
 * alias of read_defineFunction2
 * for flasm compatibility
 */
function read_function2($buf){
	return read_defineFunction2($buf);
}

function read_Try($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$buf = substr($buf, 0, $ard["totalLength"]);

	$tryFlag = get_binData_string($buf[3]);

	$tfAr = array();
	$tfAr["catchInRegister"] = (int) $tryFlag[5];
	$tfAr["finallyBlock"]	= (int) $tryFlag[6];
	$tfAr["catchBlock"]		= (int) $tryFlag[7];
	$ard["tryFlags"] = $tfAr;

	$ard["trySize"] = 0;
	$ard["catchSize"] = 0;
	$ard["finallySize"] = 0;

	$ofst = 4;
	$ard["trySize"] = ui16dec(substr($buf, $ofst, 2));

	$ofst += 2;
	$ard["catchSize"] = ui16dec(substr($buf, $ofst, 2));

	$ofst += 2;
	$ard["finallySize"] = ui16dec(substr($buf, $ofst, 2));

	$ofst += 2;

	if(!$tfAr["catchInRegister"]){
		$ard["catchName"] = read_swf_string(substr($buf, $ofst));
		$ofst += strlen($ard["catchName"]) + 1;
	}
	else {
		$ard["catchRegister"] = ui8dec($buf[$ofst]);
		$ofst++;
	}

	$ard["codeSize"] = $ard["trySize"] + $ard["catchSize"] + $ard["finallySize"];

	return $ard;
}


function read_tryBody($buf){

}

function read_catchBody($buf){

}

function read_finallyBody($buf){

}

// ---------------- end of swf_read... functions block -------------

/**
 * private
 * returns paramType from paramCode
 */
function get_paramType($paramCode){
	global $asTL;
	return $asTL[$paramCode];
}


/**
 * returns actionName from given actionCode
 */
function get_actionName($actionCode){

	global $swfActionTrans_luStr, $swfActionTrans_luAr;

	$strAC = "x" .$actionCode;
	return $swfActionTrans_luAr[$strAC];

}

/**
 * private
 * returns actionCode from given actionName
 */
function get_actionCode($actionName){
	global $swfActions;

	if(is_supported_action($actionName)) return($swfActions[$actionName]);
	else return 0;
}


/**
 * reads first three bytes of an action record buf
 * return an associative array filled with action record header data
 */
function get_actionRecord_header($buf){

	$ard = array();
	$ard["actionCode"] = ui8dec($buf[0]);
	$ard["actionName"] = get_actionName($ard["actionCode"]);
	$ard["totalLength"] = 1;

	if(strlen($buf) >= 3)
		$ard["totalLength"] = ui16dec(substr($buf, 1, 2)) + 3;

	return $ard;
}

/**
 * private
 * reads data
 * fills and returns an associative array
 * with action record data
 */
function read_actionRecord_data($buf){

	$ard = get_actionRecord_header(substr($buf, 0, 3));
	$ard["totalLength"] = 1;

	if($ard["actionCode"] >= 0x80){
		$strFunc = "read_" .ucfirst($ard["actionName"]) ."(\$buf);";
		eval("\$ard =" .$strFunc);
	}

	return $ard;
}


/**
 * reads data
 * fills and return an associative array
 * with clipactions fields
 */
function read_clipActions_header_data($buf, $swfVersion = -1){

	if($swfVersion == -1) $swfVersion = get_global_swfVersion();

	$ceLength = $swfVersion >= 6 ? 4 : 2;

	$cad = array();

	// clipActions begins with two null bytes, so let's skip them
	$ceFlags = substr($buf, 2, $ceLength);

	$cad["ceFlags"] = read_clipEventFlags_data($ceFlags, $swfVersion);
	$cad["managedEvents"] = read_managedEvents_data($cad["ceFlags"], $swfVersion);
	$cad["caCount"] = count_bit($cad["ceFlags"], true);
	$cad["offset"] = $ceLength; // useful to find clipActions startdata

	return $cad;
}


/**
 * reads data
 * fills and return CLIPACTIONRECORD header data
 * please don't confuse with read_clipActions_header_data(...)
 * this applies to a single clipaction record
 * actions are stored as binary data
 */
function read_clipActionRecord_data($buf, $swfVersion = -1){

	if($swfVersion == -1) $swfVersion = get_global_swfVersion();
	$caData = array();
	$ceLength = $swfVersion >= 6 ? 4 : 2;
	$ceFlags = substr($buf, 0 , $ceLength);

	$caData["ceFlags"] = read_clipEventFlags_data($ceFlags, $swfVersion);
	$caData["managedEvents"] = read_managedEvents_data($caData["ceFlags"], $swfVersion);
	$caData["caSize"] = ui32dec(substr($buf, $ceLength, 4));
	$caData["totalLength"] = $ceLength + 4 + $caData["caSize"];

	$buf = substr($buf, 0, $caData["totalLength"]);
	$caData["caBuf"] = substr($buf, $ceLength + 4);

	return $caData;
}

/**
 * fills and return an array with managed events
 * from a given clipevents flags
 */
function read_managedEvents_data($ceFlags, $swfVersion = -1){

	global $cafNames;
	$med = array();

	$ceStr = decbin($ceFlags);
	if($swfVersion == -1) $swfVersion = get_global_swfVersion();

	$s = $swfVersion >= 6 ? 3 : 2;

	$padStr = str_repeat("0", $s * 8);
	$cfLength = strlen($padStr);
	$ceLength = strlen($ceStr);

	if($ceLength < $cfLength)
		$ceStr = substr($padStr, $ceLength) .$ceStr;

	$ceStr = strrev($ceStr);
	$cLength = strlen($ceStr);

	for($i = 0, $j = 1; $i < $cLength; $i++, $j *= 2){

		$cmp = $ceStr[$i];

		if($cmp == "1")
			$med[] = $cafNames["x" .$j];
	}

	return $med;
}
/**
 * reads data
 * return a number representing
 * clipEventFlags
 */
function read_clipEventFlags_data($ceFlags, $swfVersion){

	$ce = $ceFlags;

	if(strlen($ceFlags) == 4) $ce = $ceFlags[2] . $ceFlags[1] .$ceFlags[0];
	else $ce = $ceFlags[1] .$ceFlags[0];

	$ceStr = get_binData_string($ce);

	$ceDec = bindec($ceStr);

	return $ceDec;
}


/**
 * reads data
 * returns an associative array with BUTTONCONDACTION "header" fields
 */
function read_buttonCondAction_header_data($buf){

	$bcaData = array();

	$bcaData["actionSize"]		  = ui16dec(substr($buf, 0, 2));

	$bcaFlagStr = get_bindata_string(substr($buf, 2, 2));

	$bcaData["idleToOverDown"]	  = (int) $bcaFlagStr[0];
	$bcaData["outDownToIdle"]	  = (int) $bcaFlagStr[1];
	$bcaData["outDownToOverDown"] = (int) $bcaFlagStr[2];
	$bcaData["overDownToOutDown"] = (int) $bcaFlagStr[3];
	$bcaData["overDownToOverUp"]  = (int) $bcaFlagStr[4];
	$bcaData["overUpToOverDown"]  = (int) $bcaFlagStr[5];
	$bcaData["overUpToIdle"]	  = (int) $bcaFlagStr[6];
	$bcaData["idleToOverUp"]	  = (int) $bcaFlagStr[7];
	$bcaData["keyPress"]		  = bindec(substr($bcaFlagStr, 8, 7));
	$bcaData["overDownToIdle"]	  = (int) $bcaFlagStr[7];


	return $bcaData;
}


//---------------------------------------------
// WRITE FUNCTIONS
//---------------------------------------------

/**
 * private
 * writes data
 * assemble an action record data from a given
 * associative array and returns binary data
 */
function write_actionRecord_data($ard = array()){

	if(!isset($ard["actionCode"]) || $ard["actionCode"] <= 0)
		$ard["actionCode"] = get_actionCode($ard["actionName"]);

	if(!$ard["actionCode"]) return "";

	$buf = chr($ard["actionCode"]);

	if($ard["actionCode"] >= 0x80){

		$strFunc = "write_" .ucfirst($ard["actionName"]) ."(\$ard);";
		eval("\$buf = " .$strFunc);
	}

	return $buf;
}

// ----------- end of mk lib actions --------------------
?>